import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';
import router from '@/router';
import useStore from '@/store';
import QS from 'qs';
// import Cookies from 'js-cookie';
// import QS from 'qs';
import { ElMessage, ElLoading } from 'element-plus';
import { Response } from '@/types/global/request';

interface Http {
  get<T>(url: string, params?: unknown): Promise<Response<T>>;

  post<T>(url: string, params?: unknown): Promise<Response<T>>;

  upload<T>(url: string, params: unknown): Promise<Response<T>>;

  download(url: string): void;

  postDownload<T>(url: string, params: unknown): Promise<Response<T>>;
}
// 设置请求头和请求路径
axios.defaults.baseURL = import.meta.env.VITE_APP_API;
axios.defaults.timeout = 60000;
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';

//请求拦截器
axios.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    const token = useStore.setting.token;
    if (token) {
      config.headers.Authorization = 'Bearer ' + token;
    }
    if (config.method === 'get') {
      //如果是get请求，且params是数组类型如arr=[1,2]，则转换成arr=1&arr=2
      config.paramsSerializer = function (params) {
        return QS.stringify(params, { arrayFormat: 'repeat' });
      };
    }
    // else {
    //   // 重定向到登录页面
    //   router.push('/login');
    // }
    return config;
  },
  (error: Error) => {
    return Promise.reject(error); // 在调用的那边可以拿到(catch)你想返回的错误信息
  }
);
// 响应拦截
axios.interceptors.response.use(
  (res: AxiosResponse) => {
    //发请求前做的一些处理，数据转化，配置请求头，设置token,设置loading等，根据需求去添加
    if (res.data.type == 'application/octet-stream') {
      return res;
    }
    switch (res.data.status) {
      case 200:
        return res;
      default:
        errorHandle(res.data.status, res.data.message);
        return;
    }
  },
  (error: AxiosError) => {
    // 接收到异常响应的处理开始
    if (error && error.response) {
      // 1.公共错误处理
      // 2.根据响应码具体处理
      switch (error.response.status) {
        case 400:
          error.message = '错误请求';
          break;
        case 401:
          error.message = '登录已失效，请重新登录';
          toSignIn();
          break;
        case 403:
          error.message = '拒绝访问';
          break;
        case 404:
          error.message = '请求错误,未找到该资源';
          //window.location.href = '/NotFound';
          break;
        case 405:
          error.message = '请求方法未允许';
          break;
        case 408:
          error.message = '请求超时';
          break;
        case 500:
          error.message = '服务器端出错';
          break;
        case 501:
          error.message = '网络未实现';
          break;
        case 502:
          error.message = '网络错误';
          break;
        case 503:
          error.message = '服务不可用';
          break;
        case 504:
          error.message = '网络超时';
          break;
        case 505:
          error.message = 'http版本不支持该请求';
          break;
        default:
          error.message = `连接错误${error.response.status}`;
      }
    } else {
      // 超时处理
      if (JSON.stringify(error).includes('timeout')) {
        ElMessage.error('服务器响应超时，请刷新当前页');
      }
      ElMessage.error('连接服务器失败');
    }
    ElMessage.error(error.message);
    //处理结束
    //如果不需要错误处理，以上的处理过程都可省略
    return Promise.reject(error.response);
  }
);

const Http: Http = {
  get(url, params) {
    return new Promise((resolve, reject) => {
      //const loadingInstance = ElLoading.service({ fullscreen: true })
      axios
        .get(url, { params })
        .then(res => {
          //loadingInstance.close()
          resolve(res.data);
        })
        .catch(err => {
          //loadingInstance.close()
          reject(err.data);
        });
    });
  },
  post(url, params) {
    return new Promise((resolve, reject) => {
      axios
        .post(url, params)
        .then(res => {
          resolve(res.data);
        })
        .catch(err => {
          reject(err.data);
        });
    });
  },
  upload(url, file) {
    return new Promise((resolve, reject) => {
      axios
        .post(url, file, {
          headers: { 'Content-Type': 'multipart/form-data' },
        })
        .then(res => {
          resolve(res.data);
        })
        .catch(err => {
          reject(err.data);
        });
    });
  },
  download(url) {
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    iframe.src = url;
    iframe.onload = function () {
      document.body.removeChild(iframe);
    };
    document.body.appendChild(iframe);
  },
  postDownload(url, params) {
    return new Promise((resolve, reject) => {
      axios
        .post(url, params, { responseType: 'blob' })
        .then(res => {
          debugger;
          var blob = new Blob([res.data], { type: res.headers['content-type'] });
          let fileNameCode = res.headers['content-disposition'].split(';')[1].split('filename=')[1];
          let fileName = decodeURIComponent(fileNameCode);
          var downloadElement = document.createElement('a');
          var href = window.URL.createObjectURL(blob); //创建下载的链接
          downloadElement.href = href;
          downloadElement.download = fileName; //下载后文件名
          document.body.appendChild(downloadElement);
          downloadElement.click(); //点击下载
          document.body.removeChild(downloadElement); //下载完成移除元素
          window.URL.revokeObjectURL(href); //释放掉blob对象
          resolve(res.data);
        })
        .catch(err => {
          reject(err.data);
        });
    });
  },
};

/**
 * 跳转登录页
 */
function toSignIn(): void {
  //清除setting
  useStore.setting.$reset();
  setTimeout(() => {
    router.replace({
      path: '/login',
      // query: {
      //     redirect: router.currentRoute.fullPath
      // }
    });
  }, 1000);
}

function errorHandle(status: number, message: string): void {
  switch (status) {
    case 1:
      ElMessage.error('token无效');
      break;
    case 2:
      ElMessage.error('token过期');
      toSignIn();
      break;
    case 401:
      ElMessage.error('权限不足,请联系管理员');
      break;
    case 403:
      ElMessage.error('403');
      break;
    // case 98:
    //   Message.error(message);
    //   break;
    case 99:
      ElMessage.error('系统异常');
      break;
    default:
      ElMessage.error(message);
  }
}
export default Http;
